package cn._2dland.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONArray;
import org.json.JSONObject;

@SuppressWarnings({"serial","unused"})
public class YoukuServlet extends HttpServlet {
	private static final String YOUKU_URL_PART1 = "http://v.youku.com/player/getPlayList/VideoIDS/";
	private static final String YOUKU_URL_PART2 = "/version/5/source/video";

	private static final String YOUKU_VIDEOURL_PREFIX = "http://f.youku.com/player/getFlvPath/sid/";
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String vid = req.getParameter("vid");
		try{
			if(vid == null) throw new Exception("");

			String jsonURL = YOUKU_URL_PART1 + vid + YOUKU_URL_PART2;
			JSONObject obj = getJSONObject(jsonURL);
			JSONArray datas = obj.getJSONArray("data");
			if(datas.length() < 1) throw new Exception("No datas!");

			JSONObject data = datas.getJSONObject(0);
			String xml = getVideoXML(data);

			resp.setContentType("text/xml; charset=UTF-8");
			resp.setCharacterEncoding("utf-8");
			resp.getWriter().print(xml);
		}
		catch(Exception e){
			e.printStackTrace();
			resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}
	}

	/**
	 * 读取远程的JSON文本，并转换为JSON对象
	 * @param jsonURL
	 * @return
	 */
	private JSONObject getJSONObject(String jsonURL) throws Exception {
		URL url = new URL(jsonURL);
		HttpURLConnection conn = (HttpURLConnection)url.openConnection();
		conn.setDoInput(true);
		conn.connect();

		int respCode = conn.getResponseCode();
		if(respCode != HttpURLConnection.HTTP_OK)
			throw new Exception("connect failed: " + respCode);

		StringBuffer strBuff = new StringBuffer();
		InputStreamReader isr = new InputStreamReader(conn.getInputStream());
		char[] cbuf = new char[32];
		int len = 0;
		do{
			strBuff.append(cbuf, 0, len);
			len = isr.read(cbuf);
		}while(len>=0);
		isr.close();
		conn.disconnect();

		JSONObject jsonObj = new JSONObject(strBuff.toString());
		return jsonObj;
	}

	/**
	 * 根据JSON对象生成视频XML
	 * @param data
	 * @return
	 * @throws Exception
	 */
	private String getVideoXML(JSONObject data) throws Exception {
		StringBuffer xmlBuff = new StringBuffer();
		xmlBuff.append("<?xml version='1.0' encoding='UTF-8'?>\n");
		xmlBuff.append("<video>\n");
		xmlBuff.append("\t<result>suee</result>\n");

		// 获取必要的信息
		String key1 = (String)data.get("key1");
		String key2 = (String)data.get("key2");
		int seed = ((Integer)data.get("seed")).intValue();

		JSONArray types = data.getJSONArray("streamtypes");
		String type = types.getString(types.length()-1);
		if("flvhd".equals(type)) type = "flv";

		String fileID = data.getJSONObject("streamfileids").getString(type);

		// 计算路径相关的信息
		String sid = getSID();
		String key = getKey(key1, key2);
		String realFileID = getFileID(fileID, seed);

		JSONArray segs = data.getJSONObject("segs").getJSONArray(type);
		for(int i = 0; i < segs.length(); i++) {
			xmlBuff.append("\t<durl>\n");

			JSONObject segObj = segs.getJSONObject(i);
			int order = segObj.getInt("no");
			int length = segObj.getInt("seconds") * 1000;

			String idx = index2HexString(order);
			realFileID = realFileID.substring(0, 8) + idx + realFileID.substring(10);

			StringBuffer url = new StringBuffer(YOUKU_VIDEOURL_PREFIX);
			url.append(sid).append("_").append(idx).append("/st/").append(type).append("/fileid/");
			url.append(realFileID).append("?K=").append(key);

			xmlBuff.append("\t\t<order>").append(order+1).append("</order>\n");
			xmlBuff.append("\t\t<length>").append(length).append("</length>\n");
			xmlBuff.append("\t\t<url><![CDATA[").append(url).append("]]></url>\n");

			xmlBuff.append("\t</durl>\n");
		}

		xmlBuff.append("</video>");
		return xmlBuff.toString();
	}

	private String getSID() {
		Random rnd = new Random();
		StringBuffer sid = new StringBuffer();
		sid.append(System.currentTimeMillis()).append(1000 + rnd.nextInt(999)).append(1000 + rnd.nextInt(9000));
		return sid.toString();
	}

	private String getKey(String key1, String key2) {
		int appendKey = HexString2Int(key1);
		appendKey ^= 0xA55AA5A5;
		String key = key2 + Integer.toHexString(appendKey);
		return key;
	}

	private int HexString2Int(String hex) {
		int result = 0;
		for(int i = 0; i < hex.length(); i++){
			char c = hex.charAt(i);
			int b = 0;

			if(c >= '0' && c <= '9') b = c - '0';
			if(c >= 'a' && c <= 'f') b = c - 'a' + 10;
			if(c >= 'A' && c <= 'F') b = c - 'A' + 10;
			result = result << 4 | b;
		}
		return result;
	}

	private String getFileID(String fileID, int seed) {
		StringBuffer realID = new StringBuffer();
		String mixed = getMixString(seed);
		String[] ids = fileID.split("\\*");
		for(int i = 0; i < ids.length; ++i) {
			int idx = Integer.parseInt(ids[i]);
			realID.append(mixed.charAt(idx));
		}
		return realID.toString();
	}

	private String getMixString(int seed) {
		StringBuffer mix = new StringBuffer();
		StringBuffer source = new StringBuffer("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/\\:._-1234567890");
		int len = source.length();

		for(int i = 0; i < len; ++i) {
			seed = (seed * 211 + 30031) % 65536;
			int idx = (int)(seed / 65536d * source.length());
			mix.append(source.charAt(idx));
			source.deleteCharAt(idx);
		}

		return mix.toString();
	}

	private String index2HexString(int idx) {
		String hex = Integer.toHexString(idx);
		while(hex.length()<2) hex = "0" + hex;
		return hex;
	}
}
